import json
from django.http import JsonResponse
import datetime
from PIL import Image, ImageDraw, ImageFont
import random
from io import BytesIO
import jwt
from Crypto.Cipher import PKCS1_v1_5 as Cipher_pksc1_v1_5
from Crypto.PublicKey import RSA
import base64
import redis
import uuid
import os
from .models import Users

pool = redis.ConnectionPool()
r = redis.Redis(connection_pool=pool)
dir_path = os.path.dirname(__file__)  # 当前文件路径


class VerificationCodeImg:
    def __init__(self, width=120, height=35, code_count=4, font_size=32, point_count=0, line_count=0,
                 img_format="png"):
        self.width = width
        self.height = height
        self.code_count = code_count
        self.font_size = font_size
        self.point_count = point_count
        self.line_count = line_count
        self.img_format = img_format

    @staticmethod
    def getRandomColor():
        c1 = random.randint(0, 255)
        c2 = random.randint(0, 255)
        c3 = random.randint(0, 255)
        return c1, c2, c3

    @staticmethod
    def getRandomStr():
        random_num = str(random.randint(0, 9))
        random_low_letter = chr(random.randint(97, 122))
        random_upper_letter = chr(random.randint(65, 90))
        random_char = random.choice(
            [random_num, random_low_letter, random_upper_letter])
        return random_char

    def getVerificationCode(self):
        img = Image.new("RGBA", (120, 35))
        draw = ImageDraw.Draw(img)
        font = ImageFont.truetype(dir_path + '\\font\\cmmi10.ttf', size=25)
        temp_list = []
        for i in range(self.code_count):
            random_char = self.getRandomStr()
            draw.text((10 + i * 30, 0), random_char,
                      self.getRandomColor(), font=font)
            temp_list.append(random_char)
        vaild_str = ''.join(temp_list)
        for i in range(self.line_count):
            x1 = random.randint(0, self.width)
            x2 = random.randint(0, self.width)
            y1 = random.randint(0, self.height)
            y2 = random.randint(0, self.height)
            draw.line((x1, y1, x2, y2), fill=self.getRandomColor())
        for i in range(self.point_count):
            draw.point([random.randint(0, self.width), random.randint(
                0, self.height)], fill=self.getRandomColor())
            x = random.randint(0, self.width)
            y = random.randint(0, self.height)
            draw.arc((x, y, x + 4, y + 4), 0, 90, fill=self.getRandomColor())
        # 在内存中生成图片

        f = BytesIO()
        img.save(f, self.img_format)
        data = f.getvalue()
        f.close()
        return data, vaild_str


# RSA解密
def rsa_decrypt(encrypt_msg):
    with open(dir_path + "\\key\\pri.key", "r", encoding="utf-8") as f:
        pri = f.read()  # 解密私钥
        private_key = "-----BEGIN PRIVATE KEY-----\n" + \
                      pri + "\n-----END PRIVATE KEY-----"
        decodeStr = base64.b64decode(encrypt_msg)
        rsa_key = RSA.importKey(private_key)
        pri_key = Cipher_pksc1_v1_5.new(rsa_key)
        encry_text = pri_key.decrypt(decodeStr, b"rsa")
        return encry_text.decode("utf8")


# token加密
def token_encryption(user, duration):  # 需要两个参数，用户登录信息和token保存时长（第二个参数表示天数）
    salt = "*&&%^%#$$"
    payload = {
        "user_account": user["user_account"],
        "key": user["key"],
        "exp": datetime.datetime.utcnow() + datetime.timedelta(days=duration),  # exp 配置token有效时长天数
    }
    token = jwt.encode(payload=payload, key=salt, algorithm="HS256")
    # encoded_jwt = str(token, encoding="ascii")
    return token


def verification_code(request):
    res = {"code": 400, "message": "", "data": None}
    image = VerificationCodeImg()
    data_img, code = image.getVerificationCode()
    uid = str(uuid.uuid4())
    uu_code = ''.join(uid.split("-"))
    try:
        r.set(uu_code, code)
        baseImg = base64.b64encode(data_img)
        return JsonResponse({"code": 200, "data": {"img": baseImg.decode(), "code": uu_code}})
    except Exception as e:
        res["message"] = "服务器错误：" + str(e)
        return JsonResponse(res)


def check_user(request):
    res = {"code": 400, "message": "", "data": None}
    try:
        user_account = request.GET.get("user_account")
        data = Users.objects.filter(user_account=user_account).values().first()
        if not data:
            res['message'] = '用户账号可用'
            res['code'] = 200
        else:
            res['message'] = "用户已注册"
    except Exception as e:
        res['message'] = '服务器错误：' + str(e)
        res['code'] = 500
    return JsonResponse(res)


# class UserApiView(APIView):


def create_user(request):
    res = {"code": 400, "message": "", "data": None}
    if request.method == "POST":
        try:
            data = json.loads(request.body)
            data["create_date"] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            # 创建一个 User 对象
            user = Users.objects.create(**data)
            user.save()
            res["code"] = 200
            res["message"] = "success"
        except Exception as e:
            res["code"] = 500
            res["message"] = "服务器错误：" + str(e)
    else:
        res["message"] = "请使用POST方法"
    return JsonResponse(res)


def change_password(request):
    res = {"code": 400, "message": "", "data": None}
    if request.method == 'POST':
        try:
            data = json.loads(request.body)
            db_data = Users.objects.filter(user_account=data["user_account"]).values().first()
            db_psd = rsa_decrypt(db_data['password'])
            # 前端密码解密
            req_psd = rsa_decrypt(data["old_password"])
            if req_psd == db_psd:
                Users.objects.filter(user_account=data['user_account']).update(password=data['new_password'])
                res['code'] = 200
                res['message'] = '修改成功'
            else:
                res['message'] = '原始密码错误'
        except Exception as e:
            res['code'] = 500
            res["message"] = "服务器错误：" + str(e)
    else:
        res['message'] = '请使用POST方式提交'
    return JsonResponse(res)


def modify_user(request):
    res = {"code": 400, "message": "", "data": None}
    if request.method == 'POST':
        try:
            data = json.loads(request.body)
            Users.objects.filter(user_account=data["user_account"]).update(**data)
            res_data = Users.objects.filter(user_account=data['user_account']).values().first()
            del res_data["password"]
            del res_data['key']
            del res_data['id']
            res_data['create_date'] = datetime.datetime.fromisoformat(str(res_data['create_date'])) \
                .strftime("%Y-%m-%d %H:%M:%S")
            res["code"] = 200
            res['message'] = '更新成功'
            res['data'] = res_data
        except Exception as e:
            res["code"] = 500
            res["message"] = "服务器错误：" + str(e)
    else:
        res["message"] = "请使用POST方法"
    return JsonResponse(res)


def user_login(request):
    res = {"code": 400, "message": "", "data": None}
    try:
        req = json.loads(request.body)
        rcode = r.get(req["code"])
        if not rcode:
            res["message"] = "验证码不存在，请重新刷新验证码"
            return JsonResponse(res)
        if rcode.decode() != req["verification"]:
            res["message"] = "验证码不正确"
            r.delete(req["code"])
            return JsonResponse(res)
        data = Users.objects.filter(user_account=req["user_account"]).values().first()
        if data and data['user_account']:
            # 数据库密码解密
            db_psd = rsa_decrypt(data['password'])
            # 前端密码解密
            req_psd = rsa_decrypt(req["password"])
            if db_psd == req_psd:
                uid = str(uuid.uuid4())
                uu_code = ''.join(uid.split("-"))
                token = token_encryption({"user_account": data["user_account"], "key": uu_code}, 3)
                Users.objects.filter(id=data['id']).update(key=uu_code)
                del data["password"]
                del data['key']
                del data['id']
                data['create_date'] = datetime.datetime.fromisoformat(str(data['create_date'])) \
                    .strftime("%Y-%m-%d %H:%M:%S")
                res["code"] = 200
                res["message"] = "success"
                response_data = {"user_data": data, "token": token}
                res["data"] = response_data
            else:
                res['message'] = "密码输入错误"
        else:
            res["message"] = "用户不存在"

    except Exception as e:
        res["message"] = "服务器错误，错误原因：" + str(e)
        res["code"] = 500
    r.delete(req["code"])
    return JsonResponse(res)
